#if ByteDance
using System;
using UnityEngine;
using ByteDance.Union;

public partial class ByteDanceAdController :MonoBehaviour, AdController
{
    public enum AdType
    {
        Test,
        Android,
        IOS,
    }

    AdType curAdType
    {
        get
        {
            if (Application.platform == RuntimePlatform.IPhonePlayer)
            {
                return AdType.IOS;
            }
            else if (Application.platform == RuntimePlatform.Android)
            {
                return AdType.Android;
            }
            else
            {
                GameDebug.LogError($"ad current unsupport platform:{Application.platform}");
                return AdType.Test;
            }
        }
    }
    
    string bannerAdUnitId
    {
        get
        {
            if (curAdType == AdType.Android)
                return "946510450";
            else if (curAdType == AdType.IOS)
                return "946512926";
            else
                return "";
        }
    }
    
    string interstitialAdUnitId
    {
        get
        {
            if (curAdType == AdType.Android)
                return "946510476";
            else if (curAdType == AdType.IOS)
                return "946512921";
            else
                return "";
        }
    }
    
    string rewardAdUnitId
    {
        get
        {
            if (curAdType == AdType.Android)
                return "946510487";
            else if (curAdType == AdType.IOS)
                return "946512929";
            else
                return "";
        }
    }

    string splashAdUnitId
    {
        get
        {
            if (curAdType == AdType.Android)
                return "887534404";
            else if (curAdType == AdType.IOS)
                return "887534777";
            else
                return "";
        }
    }

    static string iosappId = "5192041";

    /// <summary>
    /// Banner Ad
    /// </summary>   
    private AdNative adNative;
    private AdNative AdNative
    {
        get
        {
            if (this.adNative == null)
            {
                this.adNative = SDK.CreateAdNative();
            }

            return this.adNative;
        }
    }
    private ExpressAd mExpressBannerAd;

    /// <summary>
    /// Interstitial Ad
    /// </summary>
    /// 
    private FullScreenVideoAd fullScreenVideoAd;

    /// <summary>
    /// Video Ad
    /// </summary>
    private RewardVideoAd rewardAd;
    bool m_VideoLoaded;
    bool m_VideoClosed;
    bool m_VideoSuc;

    /// <summary>
    /// �������
    /// </summary>
    private BUSplashAd splashAd;


#if UNITY_IOS
    private ExpressRewardVideoAd expressRewardAd; // for iOS
    private ExpressFullScreenVideoAd expressFullScreenVideoAd; // for iOS
    private ExpressBannerAd iExpressBannerAd; // for iOS
    private ExpressInterstitialAd iExpressInterstitialAd; // for iOS
#else

#endif

    private AndroidJavaObject mNativeAd;
    private AndroidJavaObject activity;
    private AndroidJavaObject mNativeAdManager;
    public void Init()
    {
        Debug.Log($"bytedance Init bannerAdUnitId :{this.bannerAdUnitId}  interstitialAdUnitId :{this.interstitialAdUnitId}  rewardAdUnitId :{this.rewardAdUnitId}");

        //Must be called after initialization, otherwise it will be null_  
        this.adNative = SDK.CreateAdNative();

#if UNITY_IOS

        PangleConfiguration configuration = PangleConfiguration.CreateInstance();
        configuration.appID = iosappId;
#endif
        Pangle.InitializeSDK(OnInitResult);

        //AudienceNetwork.AdSettings.AddTestDevice("807e73b2-4202-40c6-8b4b-993d8347e00f");
    }

    private void OnInitResult(bool success, string message)
    {
        GameDebug.LogError($"bytedance init result:{success}  message:{message}");

        LoadSplashAd();
    }

    public AndroidJavaObject GetActivity()
    {
        if (activity == null)
        {
            var unityPlayer = new AndroidJavaClass(
            "com.unity3d.player.UnityPlayer");
            activity = unityPlayer.GetStatic<AndroidJavaObject>(
           "currentActivity");
        }
        return activity;
    }

#region SplashAd

    private AndroidJavaObject mSplashAdManager;

    public const int SPLASH_TIME_OUT = 3000;

    public void LoadSplashAd()
    {
#if UNITY_IOS
        if (this.splashAd != null)
        {
            this.splashAd.Dispose();
            this.splashAd = null;
        }
        //if (this.expressSplashAd != null)
        //{
        //   this.expressSplashAd.Dispose();
        //    this.expressSplashAd = null;
        //}
#endif

        var adSlot = new AdSlot.Builder()
            .SetCodeId(splashAdUnitId)
            .SetImageAcceptedSize(1080, 1920)
            .Build();
#if UNITY_IOS
        this.splashAd = (this.AdNative.LoadSplashAd_iOS(adSlot, new SplashAdListener(this)));
#else
        this.AdNative.LoadSplashAd(adSlot, new SplashAdListener(this, GetActivity(), GetSplashAdManager()), SPLASH_TIME_OUT);
#endif
    }
    public AndroidJavaObject GetSplashAdManager()
    {
        if (mSplashAdManager != null)
        {
            return mSplashAdManager;
        }
        var jc = new AndroidJavaClass(
            "com.bytedance.android.SplashAdManager");
        mSplashAdManager = jc.CallStatic<AndroidJavaObject>("getSplashAdManager");
        return mSplashAdManager;
    }

#endregion

#region RewardAd

    public void LoadVideoAd()
    {
        Debug.Log("ByteDance -> LoadVideoAd");

        var rit = this.rewardAdUnitId;
#if UNITY_IOS
        if (this.rewardAd != null)
        {
            this.rewardAd.Dispose();
            this.rewardAd = null;
        }
#else
        if (this.rewardAd != null)
        {
            Debug.LogError("����Ѿ�����");
            return;
        }
#endif

        var adSlot = new AdSlot.Builder()
            .SetCodeId(rit)
            .SetImageAcceptedSize(1080, 1920)
            //.SetRewardName("���") // rewardname ,the data filled in by the platform shall prevail
            //.SetRewardAmount(3) // rewardamount ,the data filled in by the platform shall prevail
            .SetUserID("user1") // �û�id,�ش�����
            .SetMediaExtra(Time.time.ToString()) // ���Ӳ�������ѡ
            .SetOrientation(AdOrientation.Vertical) // ���������������Ƶ�Ĳ��ŷ���
            .Build();

        this.AdNative.LoadRewardVideoAd(
            adSlot, new RewardVideoAdListener(this));
    }

    public void PlayVideoAd()
    {
        Debug.Log("ByteDance -> PlayerVideo");

        if (this.rewardAd == null)
        {
            MGame.instance.ShowNoticePanel(Localization.instance.GetValue("ad_not_ready"));
            return;
        }
        this.rewardAd.ShowRewardVideoAd();
#if UNITY_IOS
#else
        this.rewardAd = null;
#endif
    }

    public void HandleRewardedAdLoaded()
    {
        Debug.Log("RewardedVideo ad loaded.");
        m_VideoLoaded = true;
        m_VideoClosed = false;
        this.onVideoAdLoaded?.Invoke("");
    }

    public void HandleRewardedAdFailedToLoad(string error)
    {
        Debug.Log("RewardedVideo ad failed to load with error: " + error);

        this.onVideoAdFailedToLoad?.Invoke(error);
    }

    public void HandleRewardedAdOpening()
    {
        Debug.Log("RewardedVideo ad clicked.");

        this.onVideoAdOpening?.Invoke();
    }

    public void HandleRewardedAdFailedToShow()
    {
        Debug.Log("Rewarded video ad not validated, or no response from server");

        this.onVideoAdFailedToShow?.Invoke("");

        LoadVideoAd();
    }

    public void HandleRewardedAdClosed()
    {
        Debug.Log($"Rewarded video ad did close  m_VideoSuc:{m_VideoSuc}");
        if (m_VideoSuc) return;

        m_VideoClosed = true;
        //if (m_RewardedAd != null)
        //{
        //    m_RewardedAd.Dispose();
        //}

        this.onVideoAdClosed?.Invoke();

        LoadVideoAd();
    }

    public void HandleUserEarnedReward()
    {
        Debug.Log("Rewarded video HandleUserEarnedReward.");
         m_VideoSuc = true;
        this.onVideoPlaySuc?.Invoke($"");
    }

#endregion

#region Interstitial



    public void LoadInterstitialAd()
    {
        Debug.Log("ByteDance -> LoadInterstitialAd");

        var rit = this.interstitialAdUnitId;
#if UNITY_IOS
        if (this.fullScreenVideoAd != null)
        {
            this.fullScreenVideoAd.Dispose();
            this.fullScreenVideoAd = null;
        }

#else

#endif
        var adSlot = new AdSlot.Builder()
            .SetCodeId(rit)
            .SetImageAcceptedSize(1080, 1920)
            .SetOrientation(AdOrientation.Vertical)
            .Build();
        Debug.Log("LoadFullScreenVideoAd this.name:" + this.name);
        this.AdNative.LoadFullScreenVideoAd(adSlot, new FullScreenVideoAdListener(this));

    }

    public void ShowInterstitialAd()
    {
#if UNITY_IOS
        if (this.fullScreenVideoAd == null)
        {
            Debug.LogError("bytedance ios ShowInterstitialAd");
            return;
        }
        this.fullScreenVideoAd.ShowFullScreenVideoAd();
#else
        if (this.fullScreenVideoAd == null)
        {
            Debug.LogError("���ȼ��ع��");
            return;
        }

        this.fullScreenVideoAd.ShowFullScreenVideoAd();
        this.fullScreenVideoAd = null;
#endif
    }
    public void HandleOnInterstitialAdLoaded()
    {
        Debug.Log("Interstitial ad loaded.");

        this.onInterstitialAdLoaded?.Invoke("");
    }

    public void HandleOnInterstitialAdFailedToLoad(string error)
    {
        Debug.Log("Interstitial ad failed to load with error: " + error);

        this.onInterstitialAdFailedToLoad?.Invoke(error);
    }

    public void HandleOnInterstitialAdOpened()
    {
        Debug.Log("Interstitial ad clicked.");

        this.onInterstitialAdOpening?.Invoke("");
    }
    public void HandleOnInterstitialAdComplete()
    {
        Debug.Log("Interstitial ad suc.");

        this.onInterstitialAdSuc?.Invoke("");
    }
    public void HandleOnInterstitialAdClosed()
    {
        Debug.Log("Interstitial ad did close.");

        this.onInterstitialAdClosed?.Invoke("");
    }

#endregion

#region Banner

    public void LoadBanner()
    {
        Debug.Log("bytedance LoadBanner");
        ////remove old banner
#if UNITY_IOS
        if (this.iExpressBannerAd != null)
        {
            this.iExpressBannerAd.Dispose();
            this.iExpressBannerAd = null;
        }
#else

#endif
        float expressWidth = 320;
        float expressHeight = 50;

        string ritID = this.bannerAdUnitId;
#if UNITY_IOS
        expressWidth = 320 * PangleTools.getScreenScale();
        expressHeight = 50 * PangleTools.getScreenScale();
#else

#endif
        var adSlot = new AdSlot.Builder()
                              .SetCodeId(ritID)
                              ////����ģ����view��size,��λdp��//�߶�����Ϊ0,��߶Ȼ�����Ӧ//Only Android ,you must set height for iOS
                              .SetExpressViewAcceptedSize(expressWidth, expressHeight)
                              .SetImageAcceptedSize(1080, 1920)
                             .SetAdCount(1)
                             .SetOrientation(AdOrientation.Vertical)
                             .Build();
        this.AdNative.LoadExpressBannerAd(adSlot, new ExpressAdListener(this, 1));

        Debug.Log("bytedance LoadBanner end");
    }

    public void ShowBanner()
    {
        Debug.Log("bytedance show banner");
#if UNITY_IOS
        if (this.iExpressBannerAd == null)
        {
            Debug.LogError("���ȼ��ع��");
            return;
        }

        Debug.Log("ShowExpressAd WindowSafeAreaInsetsTop---" + PangleTools.getWindowSafeAreaInsetsTop());
        Debug.Log("ShowExpressAd WindowSafeAreaInsetsLeft---" + PangleTools.getWindowSafeAreaInsetsLeft());
        Debug.Log("ShowExpressAd WindowSafeAreaInsetsBottom---" + PangleTools.getWindowSafeAreaInsetsBottom());
        Debug.Log("ShowExpressAd WindowSafeAreaInsetsRight---" + PangleTools.getWindowSafeAreaInsetsRight());
        Debug.Log("ShowExpressAd ScreenWidth---" + PangleTools.getScreenWidth());
        Debug.Log("ShowExpressAd ScreenHeight---" + PangleTools.getScreenHeight());

        //if (y < 20)
        //{
        //    y = (int)PangleTools.getScreenHeight() - 750 - (int)PangleTools.getWindowSafeAreaInsetsBottom();
        //}

        this.iExpressBannerAd.ShowExpressAd(320, 50);// 320 * PangleTools.getScreenScale(), 50 * PangleTools.getScreenScale());
#else
        if (this.mExpressBannerAd == null)
        {
            Debug.LogError("���ȼ��ع��");
            return;
        }
        //�����ֲ���� 30s--120s;�������򲻿����ֲ�
        this.mExpressBannerAd.SetSlideIntervalTime(30 * 1000);
        ExpressAdInteractionListener expressAdInteractionListener = new ExpressAdInteractionListener(this, 1);
        ExpressAdDislikeCallback dislikeCallback = new ExpressAdDislikeCallback(this, 1);
        NativeAdManager.Instance().ShowExpressBannerAd(GetActivity(), mExpressBannerAd.handle, expressAdInteractionListener, dislikeCallback);
#endif
    }

    public void HideBanner()
    {
        Debug.Log("ByteDance -> HideBanner");

       // this.AdNative = null;

       // m_BannerView = null;
    }

    public void HandleOnBannerAdLoaded()
    {
        //Debug.Log("Banner loaded");


        this.onBannerAdLoaded?.Invoke("");
    }

    public void HandleOnBannerAdFailedToLoad(string error)
    {
        Debug.Log("Banner failed to load with error: " + error);

        this.onBannerAdFailedToLoad?.Invoke(error);
    }

    public void HandleOnBannerAdOpened()
    {
        Debug.Log("Banner clicked.");

        this.onBannerAdOpening?.Invoke("");
    }

    //public void HandleOnBannerAdClosed(object sender, EventArgs args)
    //{
    //    MonoBehaviour.print("Admod HandleAdClosed event received");

    //    this.onBannerAdClosed?.Invoke("");
    //}

    //public void HandleOnBannerAdLeavingApplication(object sender, EventArgs args)
    //{
    //    MonoBehaviour.print("Admod HandleAdLeavingApplication event received");

    //    this.onBannerAdLeavingApplication?.Invoke("");
    //}

#endregion


    public void Release()
    {
        ReleaseBannerEvent();
        ReleaseInterstitialEvent();
        ReleaseVideoEvent();

#if UNITY_IOS
        if (this.rewardAd != null)
        {
            this.rewardAd.Dispose();
            this.rewardAd = null;
        }
        if (this.fullScreenVideoAd != null)
        {
            this.fullScreenVideoAd.Dispose();
            this.fullScreenVideoAd = null;
        }


        if (this.expressRewardAd != null)
        {
            this.expressRewardAd.Dispose();
            this.expressRewardAd = null;
        }
        if (this.expressFullScreenVideoAd != null)
        {
            this.expressFullScreenVideoAd.Dispose();
            this.expressFullScreenVideoAd = null;
        }
        if (this.iExpressBannerAd != null)
        {
            this.iExpressBannerAd.Dispose();
            this.iExpressBannerAd = null;
        }
#else
        //if (this.rewardAd != null)
        //{
        //    this.rewardAd = null;
        //}
        //if (this.fullScreenVideoAd != null)
        //{
        //    this.fullScreenVideoAd = null;
        //}
        //if (this.mNativeAd != null)
        //{
        //    this.mNativeAd = null;
        //}
#endif

        this.adNative = null;
    }

    public void ReleaseBannerEvent()
    {
        onBannerAdLoaded = null;
        onBannerAdFailedToLoad  = null;
        onBannerAdOpening = null;
        onBannerAdClosed  = null;
        onBannerAdLeavingApplication  = null;
#if !UNITY_IOS
        if (this.mExpressBannerAd != null)
        {
            NativeAdManager.Instance().DestoryExpressAd(mExpressBannerAd.handle);
            mExpressBannerAd = null;
        }
#endif
        HideBanner();
    }

    public void ReleaseInterstitialEvent()
    {
        onInterstitialAdLoaded = null;
        onInterstitialAdFailedToLoad = null;
        onInterstitialAdOpening = null;
        onInterstitialAdClosed = null;
        onInterstitialAdLeavingApplication = null;

        this.fullScreenVideoAd = null;
    }

    public void ReleaseVideoEvent()
    {
        onVideoAdLoaded  = null;
        onVideoAdFailedToLoad  = null;
        onVideoAdOpening   = null;
        onVideoAdFailedToShow  = null;
        onVideoPlaySuc  = null;
        onVideoAdClosed  = null;

        this.rewardAd = null;
    }



    private Action<string> m_OnBannerAdLoaded;
    public Action<string>onBannerAdLoaded
    {
        get { return m_OnBannerAdLoaded;}
        set { m_OnBannerAdLoaded = value; }
    }

    // Called when an Banner ad request failed to load.
    public Action<string> m_OnBannerAdFailedToLoad; 
    public Action<string>onBannerAdFailedToLoad
    {
        get { return m_OnBannerAdFailedToLoad;}
        set { m_OnBannerAdFailedToLoad = value; }
    }

    public Action<string> onBannerShowSuc { get; set; }
    public Action<string> onBannerShowFailed { get; set; }

    // Called when an Banner ad is clicked.
    public Action<string> m_OnBannerAdOpening;
    public Action<string>onBannerAdOpening
    {
        get { return m_OnBannerAdOpening;}
        set { m_OnBannerAdOpening = value; }
    }
    // Called when the user returned from the app after an Banner ad click.
    public Action<string> m_OnBannerAdClosed;
    public Action<string>onBannerAdClosed
    {
        get { return m_OnBannerAdClosed;}
        set { m_OnBannerAdClosed = value; }
    }
    // Called when the Banner ad click caused the user to leave the application.
    public Action<string> m_OnBannerAdLeavingApplication;
    public Action<string>onBannerAdLeavingApplication
    {
        get { return m_OnBannerAdLeavingApplication;}
        set { m_OnBannerAdLeavingApplication = value; }
    }
	 
    // Called when an Interstitial ad request has successfully loaded.
    public Action<string> m_OnInterstitialAdLoaded;
    public Action<string>onInterstitialAdLoaded
    {
        get { return m_OnInterstitialAdLoaded;}
        set { m_OnInterstitialAdLoaded = value; }
    }
    // Called when an Interstitial ad request failed to load.
    public Action<string> m_OnInterstitialAdFailedToLoad;
    public Action<string>onInterstitialAdFailedToLoad
    {
        get { return m_OnInterstitialAdFailedToLoad;}
        set { m_OnInterstitialAdFailedToLoad = value; }
    }

    public Action<string> onInterstitialAdSuc { get; set; }
    public Action<string> onInterstitialAdFail { get; set; }

    // Called when an Interstitial ad is shown.
    public Action<string> m_OnInterstitialAdOpening;
    public Action<string>onInterstitialAdOpening
    {
        get { return m_OnInterstitialAdOpening;}
        set { m_OnInterstitialAdOpening = value; }
    }
    // Called when the Interstitial ad is closed.
    public Action<string> m_OnInterstitialAdClosed;
    public Action<string>onInterstitialAdClosed
    {
        get { return m_OnInterstitialAdClosed;}
        set { m_OnInterstitialAdClosed = value; }
    }
    // Called when the Interstitial ad click caused the user to leave the application.
    public Action<string> m_OnInterstitialAdLeavingApplication;
    public Action<string>onInterstitialAdLeavingApplication
    {
        get { return m_OnInterstitialAdLeavingApplication;}
        set { m_OnInterstitialAdLeavingApplication = value; }
    }

    public Action<string> m_OnVideoAdLoaded;
    public Action<string>onVideoAdLoaded
    {
        get { return m_OnVideoAdLoaded;}
        set { m_OnVideoAdLoaded = value; }
    }
    // Called when an ad request failed to load.
    public Action<string> m_OnVideoAdFailedToLoad;
    public Action<string>onVideoAdFailedToLoad
    {
        get { return m_OnVideoAdFailedToLoad;}
        set { m_OnVideoAdFailedToLoad = value; }
    }
    // Called when an ad is shown.
    public Action m_OnVideoAdOpening;
    public Action onVideoAdOpening
    {
        get { return m_OnVideoAdOpening;}
        set { m_OnVideoAdOpening = value; }
    }
    // Called when an ad request failed to show.
    public Action<string> m_OnVideoAdFailedToShow;
    public Action<string>onVideoAdFailedToShow
    {
        get { return m_OnVideoAdFailedToShow;}
        set { m_OnVideoAdFailedToShow = value; }
    }
    // Called when the user should be rewarded for interacting with the ad.
    public Action<string> m_OnVideoUserEarnedReward;
    public Action<string>onVideoPlaySuc
    {
        get { return m_OnVideoUserEarnedReward;}
        set { m_OnVideoUserEarnedReward = value; }
    }
    // Called when the ad is closed.
    public Action  m_OnVideoAdClosed;
    public Action onVideoAdClosed
    {
        get { return m_OnVideoAdClosed;}
        set { m_OnVideoAdClosed = value; }
    }

    public bool IsVideoReady => rewardAd !=null && m_VideoLoaded;
    public bool IsInterstitialReady => fullScreenVideoAd != null;
}




#endif

